﻿using Aribaccio;
using Aribaccio.Core;
using Aribaccio.Device;
using Aribaccio.Logger;
using BDPAutodetect.Device;
using BDPAutodetect.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;

namespace BDPAutodetect.Mgrcore
{
    /// <summary>
    /// 客户机设备检测任务
    /// </summary>
    public partial class DetectJobCustomer : DetectJobBase
    {
        /// <summary>
        /// 检测指标数据
        /// </summary>
        protected MTargetDetectDto? TargetData { get; set; }
        /// <summary>
        /// 指标任务定时器
        /// </summary>
        protected DeviceTimer TargetJobTimer { get; set; }
        /// <summary>
        /// 检测设备客户机端
        /// </summary>
        protected DetectDeviceCustomer? DeviceCustomer { get; set; }
        /// <summary>
        /// 检测设备电压电流采样板
        /// </summary>
        protected DetectDeviceElectrical? DeviceElectrical { get; set; }
        /// <summary>
        /// 是否打开 设备客户机端
        /// </summary>
        protected bool IsOpenCustomer => this.DeviceCustomer?.IsOpen ?? false;
        /// <summary>
        /// 是否打开 设备电压电流采样板
        /// </summary>
        protected bool IsOpenElectrical => this.DeviceElectrical?.IsOpen ?? false;
        /// <summary>
        /// 是否打开
        /// </summary>
        public bool IsOpen => this.IsOpenCustomer && this.IsOpenElectrical;

        /// <summary>
        /// 构造函数
        /// </summary>
        public DetectJobCustomer(DeviceStationType argStationType)
            : base(argStationType, $"{argStationType.ToInt()}号工位客户机设备检测任务", 100, true, false, true)
        {
            this.TargetJobTimer = new DeviceTimer();
            //从容器中获取-检测设备管理初始化
            var detectDeviceManager = ContainerManager.Instance.GetContainerServiceRequired<DetectDeviceManager>();
            if (detectDeviceManager != null)
            {
                //客户机端
                var detectDeviceCustom = detectDeviceManager.GetDetectDevice(DeviceType.Customer, argStationType);
                if (detectDeviceCustom != null) this.DeviceCustomer = (DetectDeviceCustomer)detectDeviceCustom;
                //电压电流采样版
                var detectDeviceElectrical = detectDeviceManager.GetDetectDevice(DeviceType.Electrical);
                if (detectDeviceElectrical != null) this.DeviceElectrical = (DetectDeviceElectrical)detectDeviceElectrical;
            }
        }

        /// <summary>
        /// 初始化数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="argTData">检测数据</param>
        public override void InitData<T>(T argTData)
        {
            this.TargetData = null;
            if (argTData is MTargetDetectDto mTargetDetectDto)
            {
                this.TargetData = mTargetDetectDto;
            }
        }

        /// <summary>
        /// 停止检测
        /// </summary>
        public override async Task StopDetect()
        {
            this.DetectStatus = DetectJobStatus.Pause;
            await base.StopDetect();
        }

        /// <summary>
        /// 继续检测
        /// </summary>
        public override async Task ContinueDetect()
        {
            this.DetectStatus = DetectJobStatus.StartDetect;
            await Task.CompletedTask;
        }

        /// <summary>
        /// 执行线程任务
        /// </summary>
        protected override void ExecuteTaskAction()
        {
            try
            {
                this.ExecuteDetect();
            }
            catch (Exception ep)
            {
                this.DetectStatus = DetectJobStatus.Error;
                LoggerMgrcore.Instance.WriteError($"{this.Name} ExecuteTaskAction Exception", ep);
            }
            finally
            {
                if (this.DetectStatus != DetectJobStatus.Error && this.DetectStatus != DetectJobStatus.Pause)
                {
                    this.DetectStatus = DetectJobStatus.Finish;
                }
                //激活主线程
                base.ActiveMain();
            }
        }

        protected void ExecuteDetect()
        {
            if (this.DetectStatus == DetectJobStatus.Pause) return;
            //检测是否已经完成
            if (this.TargetData == null || this.TargetData.DetectStatus == DetectJobStatus.Finish) return;
            //设置检测开始
            this.TargetData.SetDetectSwitch(SwitchType.On);
            //先检测设备连接状态
            if (!this.IsOpen)
            {
                this.TargetData.SetDetectResultStatus("设备未连接", string.Empty, ReceiveStatus.NC);
                this.TargetData.DetectStatus = DetectJobStatus.Finish;
                this.DetectStatus = DetectJobStatus.Error;
                return;
            }
            if (this.DetectStatus == DetectJobStatus.Pause) return;
            //检测指标
            bool bResult = this.ExecuteDetectTarget(this.TargetData);
            if (this.DetectStatus != DetectJobStatus.Pause)
            {
                this.TargetData.DetectStatus = DetectJobStatus.Finish;
            }
            if (!bResult)
            {
                this.DetectStatus = DetectJobStatus.Error;
            }
        }

        /// <summary>
        /// 执行指标检测
        /// </summary>
        /// <param name="argTargetDetectDto">检测指标参数数据</param>
        protected bool ExecuteDetectTarget(MTargetDetectDto argTargetDetectDto)
        {
            bool bResult = true;
            string detectResult = string.Empty;
            string detectResultValue = string.Empty;
            ReceiveStatus detectResultStatus = ReceiveStatus.NC;
            try
            {
                if (argTargetDetectDto.ParameterLimit != null && argTargetDetectDto.ParameterLimit.TargetSlave != null)
                {
                    var targetSlave = argTargetDetectDto.ParameterLimit.TargetSlave;
                    if (targetSlave.PermissionStatus == ExecuteStatus.Yes)
                    {
                        int nCount = 0;
                        //启动定时器，设定时长
                        this.TargetJobTimer.Start(argTargetDetectDto.ParameterLimit.LimitTime * 1000);
                        while (true)
                        {
                            if (this.DetectStatus == DetectJobStatus.Pause)
                            {
                                detectResult = string.Empty;
                                detectResultStatus = ReceiveStatus.None;
                                break;
                            }
                            //读取设备指标数据, 解析结果数据
                            if (detectResultStatus != ReceiveStatus.OK && nCount < 3)
                            {
                                Tuple<string, string, ReceiveStatus> tupleDetectResult = this.DetectDeviceData(targetSlave, argTargetDetectDto.ParameterLimit);
                                detectResult = tupleDetectResult.Item1;
                                detectResultValue = tupleDetectResult.Item2;
                                detectResultStatus = tupleDetectResult.Item3;
                                nCount++;
                            }
                            if (nCount >= 3) break;
                            if (this.TargetJobTimer.IsTimeout()) break;
                            if (detectResultStatus == ReceiveStatus.OK && targetSlave.DetectWaitStatus == ExecuteStatus.No) break;                          
                        }
                    }
                    else
                    {
                        detectResultStatus = ReceiveStatus.OK;
                    }
                }
            }
            catch (Exception ep)
            {
                LoggerMgrcore.Instance.WriteError($"{this.Name} ExecuteDetectTarget Exception", ep);
            }
            finally
            {
                if (argTargetDetectDto.TargetType == DeviceTargetType.Customer_DebugModeCheck && detectResultStatus != ReceiveStatus.OK)
                {
                    bResult = false;
                }
                //存储检测数据
                argTargetDetectDto.SetDetectResultStatus(detectResult, detectResultValue, detectResultStatus);
            }
            return bResult;
        }

        /// <summary>
        /// 检测设备数据
        /// </summary>
        /// <param name="argTargetSlave">指标协议信息对象</param>
        /// <param name="argParameterLimit">指标参数界限</param>
        /// <returns></returns>
        protected Tuple<string, string, ReceiveStatus> DetectDeviceData(MTargetSlave argTargetSlave, MParameterLimitData argParameterLimit)
        {
            //判断是否存在映射关联指标
            if (argTargetSlave.TargetMap != null && argTargetSlave.TargetMap.TargetType != DeviceTargetType.None)
            {
                //目前只支持电流电压采样板类型
                switch (argTargetSlave.TargetMap.TargetCategory)
                {
                    case DeviceType.Electrical:
                        //获取设备数据
                        decimal dDetectData = this.GetDeviceElectricalData(argTargetSlave.TargetMap.TargetType, argTargetSlave.GetDataUnitCoefficient());
                        ReceiveStatus resultStatus = this.CheckResultLimit(argParameterLimit, dDetectData);
                        return new Tuple<string, string, ReceiveStatus>(dDetectData.ToString(), dDetectData.ToString(), resultStatus);
                    case DeviceType.Customer:
                    case DeviceType.SensorSign:
                    default: return new Tuple<string, string, ReceiveStatus>(string.Empty, string.Empty, ReceiveStatus.OK);
                }
            }
            else
            {
                return this.DetectDeviceTarget(argTargetSlave, argParameterLimit);
            }
        }

        /// <summary>
        /// 检测设备指标数据
        /// </summary>
        /// <param name="argTargetSlave">指标协议信息对象</param>
        /// <param name="argParameterLimit">指标参数界限</param>
        /// <returns></returns>
        protected Tuple<string, string, ReceiveStatus> DetectDeviceTarget(MTargetSlave argTargetSlave, MParameterLimitData argParameterLimit)
        {
            //判断是否不检查的指标
            if (string.IsNullOrEmpty(argTargetSlave.SlaveCommand))
            {
                return new Tuple<string, string, ReceiveStatus>(string.Empty, string.Empty, ReceiveStatus.OK);
            }
            //定义参数
            string strOutputCommand = argTargetSlave.CheckCommand ?? string.Empty;
            bool bIsWaitResult = argTargetSlave.SendWaitStatus == ExecuteStatus.Yes;

            //获取设备数据
            var resultData = this.DeviceCustomer?.ReadDeviceData(argTargetSlave.SlaveCommand, strOutputCommand, bIsWaitResult);
            if (!bIsWaitResult) return new Tuple<string, string, ReceiveStatus>(string.Empty, string.Empty, ReceiveStatus.OK);

            AsciiSlaveData? slaveData = resultData != null ? resultData.Data : null;
            return this.ParseTargetDataLimit(slaveData, argParameterLimit);
        }

        /// <summary>
        /// 获取检测设备电压电流采样板数据
        /// </summary>
        /// <param name="argTargetType">指标类型</param>
        /// <param name="argCoefficient">数据单位转换系数</param>
        /// <returns></returns>
        protected decimal GetDeviceElectricalData(DeviceTargetType argTargetType, decimal argCoefficient)
        {
            if (!this.IsOpenElectrical) return 0;
            var resultData = this.DeviceElectrical?.ReadDeviceDataDecimal(this.StationType, argTargetType);
            decimal dResult = (resultData != null && resultData.ResultState) ? resultData.Data : 0;
            //电流 单位 A=> mA
            if (argCoefficient > 0)
            {
                dResult = dResult * argCoefficient;
            }
            return dResult;
        }

        /// <summary>
        /// 解析客户机端指标数据
        /// </summary>
        /// <param name="argSlaveData">检测设备指标数据</param>
        /// <param name="argParameterLimit"></param>
        /// <returns></returns>
        protected Tuple<string, string, ReceiveStatus> ParseTargetDataLimit(AsciiSlaveData? argSlaveData, MParameterLimitData argParameterLimit)
        {
            string resultMsg = string.Empty;
            string resultValue = string.Empty;
            ReceiveStatus resultStatus = ReceiveStatus.NG;
            if (argSlaveData == null || argParameterLimit.TargetSlave == null)
            {
                return new Tuple<string, string, ReceiveStatus>(resultMsg, resultValue, resultStatus);
            }
            try
            {
                //检测界限检查
                switch (argParameterLimit.TargetSlave.Target.TargetType)
                {
                    //测试Case
                    case DeviceTargetType.Customer_NTCTemperature:
                        if (argSlaveData.Data == "E1")
                        {
                            resultMsg = $"故障 {argSlaveData.Data}";
                        }
                        else
                        {
                            if (argSlaveData.DataBytes != null)
                            {
                                //int nMode = argSlaveData.DataBytes[0];
                                //第一位模式暂时不考虑，全部实正数,温度是0.1的精度
                                byte[] dataBytes = argSlaveData.DataBytes.Skip(1).Take((argSlaveData.DataBytes.Length - 1)).ToArray();
                                string strData = dataBytes.ToAsciiString();
                                decimal dNTCTemp = Convert.ToDecimal(strData) * 0.1m;
                                resultMsg = dNTCTemp.ToString();
                                resultValue = resultMsg;
                                resultStatus = CheckResultLimit(argParameterLimit, dNTCTemp);
                            }
                        }
                        break;
                    //测试Case
                    case DeviceTargetType.Customer_EnvironmentTemperature:
                        if (argSlaveData.Data == "E2")
                        {
                            resultMsg = $"故障 {argSlaveData.Data}";
                        }
                        else
                        {
                            resultMsg = argSlaveData.Data;
                            resultValue = argSlaveData.Data;
                            resultStatus = CheckResultLimit(argParameterLimit, Convert.ToDecimal(argSlaveData.Data));
                        }
                        break;
                    default:
                        resultMsg = argSlaveData.ToString();
                        resultValue = resultMsg;
                        resultStatus = CheckResultLimit(argParameterLimit, resultMsg);
                        break;
                }
            }
            catch (Exception ep)
            {
                LoggerMgrcore.Instance.WriteError($"{this.Name} ParseTargetDataLimit Exception", ep);
            }
            return new Tuple<string, string, ReceiveStatus>(resultMsg, resultValue, resultStatus);
        }

        /// <summary>
        /// 界限检查
        /// </summary>
        /// <returns></returns>
        protected ReceiveStatus CheckResultLimit(MParameterLimitData argParameterLimit, string argDetectData)
        {
            if (string.IsNullOrEmpty(argParameterLimit.Limit)) return ReceiveStatus.OK;
            if (string.IsNullOrEmpty(argDetectData)) return ReceiveStatus.NG;
            return argParameterLimit.Limit.Equals(argDetectData, StringComparison.OrdinalIgnoreCase) ? ReceiveStatus.OK : ReceiveStatus.NG;
        }

        /// <summary>
        /// 界限检查
        /// </summary>
        /// <returns></returns>
        protected ReceiveStatus CheckResultLimit(MParameterLimitData argParameterLimit, decimal argDetectData)
        {
            //检测界限检查
            decimal dLimit = Convert.ToDecimal(argParameterLimit.Limit);
            decimal dLimitTo = Convert.ToDecimal(argParameterLimit.LimitTo);
            return (argDetectData >= dLimit && argDetectData <= dLimitTo) ? ReceiveStatus.OK : ReceiveStatus.NG;
        }
    }
}
